package dryven.unittest;

import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import dryven.reflection.ClassTypeRef;
import dryven.reflection.LiteralTypeRef;
import dryven.reflection.TypeRef;
import dryven.unittest.models.shop.Client;
import dryven.unittest.models.shop.Product;
import dryven.unittest.models.shop.Purchase;
import dryven.view.ViewData;
import dryven.view.ViewDataDictionary;
import dryven.view.engine.expression.ExpressionCompilationException;
import dryven.view.engine.expression.CompiledViewExpression;
import dryven.view.engine.expression.ViewDataDeclaration;
import dryven.view.engine.expression.ViewExpression;
import dryven.view.engine.expression.nodelisters.DefaultNodeListerFactory;
import dryven.view.engine.expression.nodelisters.ExpressionNodeFactory;
import junit.framework.TestCase;

public class ViewExpressionTestCase extends TestCase {
	
	private Client _client;
	private Purchase _firstPurchase;
	private ViewDataDictionary _viewData;
	private Iterable<ViewDataDeclaration> _declarations;
	
	@Override
	protected void setUp() throws Exception {
		super.setUp();
		_client = new Client();
		_client.setBirthDate(new Date(1983, 3, 31));
		_client.setDni("X9221377X");
		_client.setLastname("Windels");
		_client.setName("Bruno");
		
		Product productA = new Product();
		productA.setCode("123");
		productA.setName("Product A");
		productA.setPrice(14.99);
		
		Product productB = new Product();
		productB.setCode("456");
		productB.setName("Product B");
		productB.setPrice(2.49);
		
		Purchase p1 = new Purchase();
		p1.setClient(_client);
		p1.setProduct(productA);
		p1.setPurchaseDate(new Date(2010,1,1));
		p1.setQuantity(2);
		_firstPurchase = p1;
		
		Purchase p2 = new Purchase();
		p2.setClient(_client);
		p2.setProduct(productA);
		p2.setPurchaseDate(new Date(2010,2,1));
		p2.setQuantity(3);
		
		Purchase p3 = new Purchase();
		p3.setClient(_client);
		p3.setProduct(productB);
		p3.setPurchaseDate(new Date(2010,5,1));
		p3.setQuantity(3);
		
		List<Purchase> purchases = new LinkedList<Purchase>();
		purchases.add(p1);
		purchases.add(p2);
		purchases.add(p3);
		
		_client.setPurchases(purchases);
		
		Map<String, Product> products = new HashMap<String, Product>();
		products.put("a", productA);
		products.put("b", productB);
		
		ViewData viewData = new ViewData();
		viewData.set("client", _client);
		viewData.set("firstPurchase", _firstPurchase);
		viewData.set("pi", 3.141592);
		viewData.set("products", products);
		
		_viewData = viewData;
		
		//declare types
		ExpressionNodeFactory listerFactory = new DefaultNodeListerFactory();
		TypeRef type = new ClassTypeRef(Client.class);
		String name = "client";
		ViewDataDeclaration client = new ViewDataDeclaration(type,name,listerFactory.create(type));
		type = new ClassTypeRef(Purchase.class);
		name = "firstPurchase";
		ViewDataDeclaration firstPurchase = new ViewDataDeclaration(type,name,listerFactory.create(type));
		type = new ClassTypeRef(double.class);
		name = "pi";
		ViewDataDeclaration pi = new ViewDataDeclaration(type,name,listerFactory.create(type));
		
		type = new LiteralTypeRef("[[Ljava/util/Map<Ljava/lang/String;L"+Product.class.getName().replace('.', '/')+";>;");
		name = "products";
		ViewDataDeclaration productsDecl = new ViewDataDeclaration(type,name,listerFactory.create(type));
		
		
		List<ViewDataDeclaration> declarations = new LinkedList<ViewDataDeclaration>();
		declarations.add(client);
		declarations.add(firstPurchase);
		declarations.add(pi);
		declarations.add(productsDecl);
		
		_declarations = declarations;
	}

	public void testMethodCallExpression() throws ExpressionCompilationException {
		ViewExpression expr = new ViewExpression("client.lastname", _declarations);
		CompiledViewExpression parsedExpr = expr.compile();
		Object value = parsedExpr.evaluate(_viewData);
		assertTrue(_client.getLastname()==value);
	
		expr = new ViewExpression("pi", _declarations);
		parsedExpr = expr.compile();
		value = parsedExpr.evaluate(_viewData);
		assertTrue(3.141592==((Double)value).doubleValue());
	
		expr = new ViewExpression("firstPurchase.product.price", _declarations);
		parsedExpr = expr.compile();
		value = parsedExpr.evaluate(_viewData);
		assertTrue(14.99==((Double)value).doubleValue());
		
		try {
			expr = new ViewExpression("firstPurchase.product.pric", _declarations);
			parsedExpr = expr.compile();
			assertTrue(false);
		} catch(ExpressionCompilationException e) {
			assertTrue(true);
		}
		
		try {
			expr = new ViewExpression("foo", _declarations);
			parsedExpr = expr.compile();
			assertTrue(false);
		} catch(ExpressionCompilationException e) {
			assertTrue(true);
		}
	}
	
	public void testWildchar() throws ExpressionCompilationException {
		ViewExpression expr = new ViewExpression("products.a.price", _declarations);
		CompiledViewExpression parsedExpr = expr.compile();
		Object value = parsedExpr.evaluate(_viewData);
		assertTrue(14.99==((Double)value).doubleValue());
	}
}
